#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
测试用户指定的代理列表是否可用
支持两种测试方式：
1. 调用 proxy.scdn.io 的测试API
2. 直接测试访问目标网站 data.eastmoney.com
"""

import requests
import time

# 目标测试网站
TEST_URL = "https://data.eastmoney.com"
TIMEOUT = 10  # 增加超时时间

# 网站测试API
WEBSITE_TEST_API = "https://proxy.scdn.io/api/test_proxy.php"

# 用户提供的代理列表
PROXY_LIST = [
    "14.103.138.182:8080",
    "220.178.229.83:7302",
    "218.21.91.214:80",
    "112.15.190.108:10086",
    "112.13.209.132:8080",
    "47.120.70.151:9000",
    "180.167.238.98:7302",
    "115.239.234.43:7302",
    "1.71.170.146:7302",
    "47.94.97.121:80",
]


def test_proxy_via_website_api(proxy):
    """通过网站API测试代理"""
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36 Edg/142.0.0.0',
        'Accept': '*/*',
        'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
        'Origin': 'https://proxy.scdn.io',
        'Referer': 'https://proxy.scdn.io/',
    }
    
    # 使用data参数，requests会自动处理multipart格式（当使用files时会自动切换）
    # 尝试两种格式：直接传proxy字符串，或者分开传IP和端口
    # 先尝试直接传proxy字符串
    data = {
        'proxy': proxy
    }
    
    start_time = time.time()
    try:
        r = requests.post(
            WEBSITE_TEST_API,
            data=data,
            headers=headers,
            timeout=TIMEOUT,
            verify=True
        )
        elapsed = time.time() - start_time
        
        if r.status_code == 200:
            try:
                result = r.json()
                # 检查返回结果
                if result.get('status') == 'success' or result.get('success') == True:
                    return True, f"API测试成功: {result}", elapsed
                elif result.get('status') == 'error':
                    # 虽然返回错误，但API调用了，说明格式可能不对，但不意味着代理不可用
                    error_msg = result.get('message', '未知错误')
                    if '缺少' in error_msg or 'invalid' in error_msg.lower():
                        # 可能是参数格式问题，不算失败
                        return None, f"API参数格式可能不对: {error_msg}", elapsed
                    return False, f"API返回错误: {error_msg}", elapsed
                else:
                    # 其他情况，可能是测试通过的
                    return True, f"API返回: {result}", elapsed
            except:
                # 如果不是JSON，检查文本内容
                text = r.text[:200]
                if 'success' in text.lower() or 'ok' in text.lower() or '可用' in text:
                    return True, f"API测试成功: {text}", elapsed
                elif 'error' in text.lower() or '失败' in text or 'invalid' in text.lower():
                    return False, f"API测试失败: {text[:100]}", elapsed
                else:
                    # 不确定的情况
                    return None, f"API返回: {text[:100]}", elapsed
        else:
            return False, f"API状态码: {r.status_code}", elapsed
    except Exception as e:
        elapsed = time.time() - start_time
        return False, f"API测试异常: {str(e)[:50]}", elapsed


def test_proxy_direct(proxy):
    """直接测试代理访问目标网站"""
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0',
        'Accept': '*/*',
        'Connection': 'keep-alive',
        'Accept-Language': 'zh-CN,zh;q=0.8'
    }
    
    # 格式化代理URL
    proxy_url = f"http://{proxy}"
    proxies = {
        "http": proxy_url,
        "https": proxy_url
    }
    
    start_time = time.time()
    try:
        # 先尝试 GET 方法（某些代理不支持HEAD）
        r = requests.get(
            TEST_URL,
            headers=headers,
            proxies=proxies,
            timeout=TIMEOUT,
            verify=False,
            allow_redirects=True
        )
        elapsed = time.time() - start_time
        
        if r.status_code == 200:
            return True, f"状态码: {r.status_code}", elapsed
        elif r.status_code in [301, 302, 303, 307, 308]:
            # 重定向也算成功（说明代理工作）
            return True, f"状态码: {r.status_code} (重定向)", elapsed
        else:
            return False, f"状态码: {r.status_code}", elapsed
    except requests.exceptions.Timeout:
        elapsed = time.time() - start_time
        return False, "连接超时", elapsed
    except requests.exceptions.ProxyError as e:
        elapsed = time.time() - start_time
        error_str = str(e)
        # 简化错误信息
        if "Max retries exceeded" in error_str or "HTTPSConnectionPool" in error_str:
            return False, "代理无法连接目标", elapsed
        return False, f"代理错误: {error_str[:50]}", elapsed
    except requests.exceptions.ConnectionError as e:
        elapsed = time.time() - start_time
        error_str = str(e)
        if "Remote end closed connection" in error_str:
            return False, "代理关闭连接", elapsed
        return False, f"连接错误: {error_str[:50]}", elapsed
    except Exception as e:
        elapsed = time.time() - start_time
        return False, f"其他错误: {str(e)[:50]}", elapsed


def main():
    print(f"开始测试 {len(PROXY_LIST)} 个代理...")
    print(f"测试方式：")
    print(f"  1. 网站API测试: {WEBSITE_TEST_API}")
    print(f"  2. 直接访问目标网站: {TEST_URL}")
    print(f"超时设置: {TIMEOUT} 秒\n")
    print("=" * 80)
    
    valid_proxies_api = []  # 网站API测试通过的
    valid_proxies_direct = []  # 直接测试通过的
    valid_proxies_both = []  # 两种测试都通过的
    
    for i, proxy in enumerate(PROXY_LIST, 1):
        print(f"\n[{i}/{len(PROXY_LIST)}] 测试 {proxy}")
        print(f"  {'-'*60}")
        
        # 测试1: 网站API
        print(f"  网站API测试 ... ", end="", flush=True)
        is_valid_api, error_msg_api, elapsed_api = test_proxy_via_website_api(proxy)
        if is_valid_api is True:
            print(f"✓ 通过 (耗时: {elapsed_api:.2f}秒)")
            print(f"    {error_msg_api[:80]}")
            valid_proxies_api.append(proxy)
        elif is_valid_api is None:
            print(f"⚠ 不确定 - {error_msg_api} (耗时: {elapsed_api:.2f}秒)")
        else:
            print(f"✗ 失败 - {error_msg_api} (耗时: {elapsed_api:.2f}秒)")
        
        # 测试2: 直接访问目标网站
        print(f"  目标网站测试 ... ", end="", flush=True)
        is_valid_direct, error_msg_direct, elapsed_direct = test_proxy_direct(proxy)
        if is_valid_direct:
            print(f"✓ 通过 (耗时: {elapsed_direct:.2f}秒)")
            print(f"    {error_msg_direct}")
            valid_proxies_direct.append(proxy)
            if is_valid_api:
                valid_proxies_both.append(proxy)
        else:
            print(f"✗ 失败 - {error_msg_direct} (耗时: {elapsed_direct:.2f}秒)")
    
    print("\n" + "=" * 80)
    print(f"测试结果汇总:")
    print(f"  总代理数: {len(PROXY_LIST)}")
    print(f"  网站API测试通过: {len(valid_proxies_api)} 个")
    print(f"  目标网站测试通过: {len(valid_proxies_direct)} 个")
    print(f"  两种测试都通过: {len(valid_proxies_both)} 个")
    print("=" * 80)
    
    # 优先使用两种测试都通过的，否则使用直接测试通过的
    final_valid_proxies = valid_proxies_both if valid_proxies_both else valid_proxies_direct
    
    if final_valid_proxies:
        print(f"\n可用的代理列表（用于项目）:")
        for i, proxy in enumerate(final_valid_proxies, 1):
            print(f"  {i}. {proxy}")
        
        # 生成写入命令
        print(f"\n{'='*80}")
        print("可以使用以下命令将可用代理写入代理文件:")
        print("="*80)
        print(f"sudo sh -c 'echo \"{final_valid_proxies[0]}\" > /data/instockproxy.txt'")
        for proxy in final_valid_proxies[1:]:
            print(f"sudo sh -c 'echo \"{proxy}\" >> /data/instockproxy.txt'")
        
        # 或者一次性写入所有可用代理
        print(f"\n或者一次性写入所有可用代理:")
        all_proxies = "\\n".join(final_valid_proxies)
        print(f"sudo sh -c 'echo -e \"{all_proxies}\" > /data/instockproxy.txt'")
        
        if valid_proxies_api and not valid_proxies_direct:
            print(f"\n⚠️  注意：虽然网站API测试通过了 {len(valid_proxies_api)} 个代理，")
            print(f"   但这些代理无法访问目标网站 {TEST_URL}")
            print(f"   可能是因为：")
            print(f"   1. 代理仅支持特定网站")
            print(f"   2. 目标网站对代理IP有访问限制")
            print(f"   3. 代理的测试标准和实际使用标准不同")
    else:
        print("\n很遗憾，没有找到可访问目标网站的代理")
        if valid_proxies_api:
            print(f"\n虽然网站API测试通过了 {len(valid_proxies_api)} 个代理，")
            print(f"但这些代理无法访问目标网站 {TEST_URL}。")
            print(f"可能的代理列表（仅供参考，实际使用可能失败）:")
            for i, proxy in enumerate(valid_proxies_api, 1):
                print(f"  {i}. {proxy}")
        print("\n建议:")
        print("1. 检查代理是否需要认证（格式: username:password@ip:port）")
        print("2. 尝试其他代理源")
        print("3. 检查网络连接")
        print("4. 考虑在服务器本地部署代理客户端（方案A）")


if __name__ == "__main__":
    # 禁用SSL警告
    import urllib3
    urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
    
    main()

